#pragma once
#include "ZCommon.h"
#include "ZString.h"
#include "common/ZBuffer.h"

namespace ZuiLib
{


class ZFile:public ZRefCountedBase
{
public:
	ZUI_CLASS_NAME("zui.File");
	ZFile(void);
	~ZFile(void);
	bool OpenFile(const char *file,const char *mode);

	bool OpenMem(ZBufferPtr buffer);
	bool OpenMem(const void *mem, int size);


	void Close();

	Sint64 Size();

	enum{
		ZSEEK_SET=RW_SEEK_SET,
		ZSEEK_CUR=RW_SEEK_CUR,
		ZSEEK_END=RW_SEEK_END
	};

	Sint64 Seek(Sint64 offset,int whence);
	Sint64 Tell();
	size_t Read(void *ptr,size_t size, size_t maxnum);
	size_t Write(const void *ptr,size_t size, size_t num);

	template <class T>
	size_t Write(T value)
	{
		switch(sizeof(T))
		{
		case 1:
			return WriteU8((uint8_t)value);
		case 2:
			return WriteU16((uint16_t)value);
		case 4:
			return WriteU32((uint32_t)value);
		case 8:
			return WriteU64((uint64_t)value);
		default:
			return 0;
		}
	}

	template<class T>
	void Read(T& value)
	{
		switch(sizeof(T))
		{
		case 1:
			value=(T)(ReadU8());
			break;
		case 2:
			value=(T)(ReadU16());
			break;
		case 4:
			value=(T)(ReadU32());
			break;
		case 8:
			value=(T)(ReadU64());
			break;
		default:
			ZASSERT(false);
		}
	}


	size_t WriteU8(uint8_t value);
	uint8_t ReadU8();

	size_t WriteU16(uint16_t value);
	uint16_t ReadU16();

	size_t WriteU32(uint32_t value);
	uint32_t ReadU32();

	size_t WriteU64(uint64_t value);
	uint64_t ReadU64();

	size_t WriteFloat(float value);
	float ReadFloat();

	ZIMPLEMENT_REFCOUNTING(ZFile);
private:
	SDL_RWops* m_rwops;
	ZBufferPtr m_buffer;
};

typedef ZRefCountedPtr<ZFile> ZFilePtr;

}//namespace
